﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;

namespace FlightToolkit.SimProp
{
    internal enum Policy
    {
        Unrestricted,
        Inclusive
    }

    internal class PropertySetDef : SymbolDef
    {
        internal PropertySetDef(Symbols symbols, NamespaceDef namespaceDef, XElement def)
            : base(namespaceDef, def, Cardinality.Multiple)
        {
            this.Type = symbols.LookupTypeDefByName("SET");

            var policyAttrib = def.Attribute("policy");
            if (policyAttrib != null)
            {
                this.policy = LookupPolicyByName(policyAttrib.Value);
            }

            var basedOnAttrib = def.Attribute("basedOn");
            if (basedOnAttrib != null)
            {
                PropertySetDef basedOn = namespaceDef.LookupSetDefByName(basedOnAttrib.Value);
                if (basedOn != null)
                {
                    this.properties = new List<Guid>(basedOn.properties);
                    this.propertyNames = new List<string>(basedOn.propertyNames);
                    this.propertyLocalizeOverrides = new List<Localize>(basedOn.propertyLocalizeOverrides);
                    this.propertyCardinalityOverrides = new List<Cardinality>(basedOn.propertyCardinalityOverrides);
                }
                else
                {
                    throw new Exception("Unknown basedOn set '" + basedOnAttrib.Value + "'");
                }
            }
            else
            {
                this.properties = new List<Guid>();
                this.propertyNames = new List<string>();
                this.propertyLocalizeOverrides = new List<Localize>();
                this.propertyCardinalityOverrides = new List<Cardinality>();
            }

            foreach (var prop in def.Descendants("property"))
            {
                this.propertyNames.Add(prop.Attribute("name").Value);

                Localize localize = Localize.Unknown;
                var locAttrib = prop.Attribute("localize");
                if (locAttrib != null)
                {
                    localize = SymbolDef.LookupLocalizeByName(locAttrib.Value);
                }

                Cardinality cardinality = Cardinality.Unknown;
                var cardOverAttrib = prop.Attribute("cardinality");
                if (cardOverAttrib != null)
                {
                    cardinality = SymbolDef.LookupCardinalityByName(cardOverAttrib.Value);
                }

                this.propertyLocalizeOverrides.Add(localize);
                this.propertyCardinalityOverrides.Add(cardinality);
            }
        }

        internal Policy policy;
        internal List<Guid> properties;
        internal List<string> propertyNames;
        internal List<Cardinality> propertyCardinalityOverrides;
        internal List<Localize> propertyLocalizeOverrides;

        #region Private
        private static Policy LookupPolicyByName(string name)
        {
            if (name.Equals("unrestricted", StringComparison.OrdinalIgnoreCase))
            {
                return Policy.Unrestricted;
            }
            else if (name.Equals("inclusive", StringComparison.OrdinalIgnoreCase))
            {
                return Policy.Inclusive;
            }
            else
            {
                throw new Exception("Unknown SimProp policy");
            }
        }
        #endregion
    }
}
